package no.nordicsemi.android.nrfmesh.node.dialog;

import android.os.Bundle;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.text.method.KeyListener;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import com.google.android.material.textfield.TextInputLayout;

import java.util.ArrayList;
import java.util.List;

import no.nordicsemi.android.mesh.utils.MeshParserUtils;
import no.nordicsemi.android.nrfmesh.R;
import no.nordicsemi.android.nrfmesh.databinding.LayoutVendorModelBottomSheetBinding;
import no.nordicsemi.android.nrfmesh.utils.HexKeyListener;
import no.nordicsemi.android.nrfmesh.utils.Utils;

public class BottomSheetVendorDialogFragment extends BottomSheetDialogFragment {
    private static final String KEY_INDEX = "KEY_INDEX";
    private static final String MODEL_ID = "MODEL_ID";

    private LayoutVendorModelBottomSheetBinding binding;
    private int mModelId;
    private int mKeyIndex;

    public interface BottomSheetVendorModelControlsListener {
        void sendVendorModelMessage(final int modelId, final int keyIndex, final int opCode, final byte[] parameters, final boolean acknowledged);
    }

    public static BottomSheetVendorDialogFragment getInstance(final int modelId, final int appKeyIndex) {
        final BottomSheetVendorDialogFragment fragment = new BottomSheetVendorDialogFragment();
        final Bundle args = new Bundle();
        args.putInt(MODEL_ID, modelId);
        args.putInt(KEY_INDEX, appKeyIndex);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(@Nullable final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mModelId = getArguments().getInt(MODEL_ID);
            mKeyIndex = getArguments().getInt(KEY_INDEX);
        }
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) {
        binding = LayoutVendorModelBottomSheetBinding.inflate(getLayoutInflater());
        final KeyListener hexKeyListener = new HexKeyListener();

        // 设置 opCode 字段
        binding.opCode.setKeyListener(hexKeyListener);
        binding.opCode.addTextChangedListener(new TextWatcher() {
            @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
            @Override public void onTextChanged(CharSequence s, int start, int before, int count) {
                binding.opCodeLayout.setError(null);
            }
            @Override public void afterTextChanged(Editable s) {}
        });

        // 添加按钮：动态添加波形输入框
        binding.addWaveBtn.setOnClickListener(v -> {
            EditText paramInput = new EditText(requireContext());
            paramInput.setHint("参数（如 A1B2）");
            paramInput.setKeyListener(hexKeyListener);
            paramInput.setInputType(android.text.InputType.TYPE_CLASS_TEXT);
            binding.waveFormContainer.addView(paramInput);
        });

        // 默认添加一个输入框
        binding.addWaveBtn.performClick();

        // 发送按钮点击
        binding.actionSend.setOnClickListener(v -> {
            binding.receivedMessageContainer.setVisibility(View.GONE);
            binding.receivedMessage.setText("");
            final String opCode = binding.opCode.getEditableText().toString().trim();

            if (!validateOpcode(opCode, binding.opCodeLayout)) return;

            // 收集所有输入参数
            List<Byte> byteList = new ArrayList<>();
            for (int i = 0; i < binding.waveFormContainer.getChildCount(); i++) {
                View view = binding.waveFormContainer.getChildAt(i);
                if (view instanceof EditText) {
                    String input = ((EditText) view).getText().toString().trim();
                    if (!TextUtils.isEmpty(input)) {
                        try {
                            byte[] bytes = MeshParserUtils.toByteArray(input);
                            for (byte b : bytes) byteList.add(b);
                        } catch (Exception e) {
                            Utils.showToast(requireContext(), "第 " + (i + 1) + " 个参数无效");
                            return;
                        }
                    }
                }
            }

            // 转换成 byte[]
            byte[] params = new byte[byteList.size()];
            for (int i = 0; i < byteList.size(); i++) {
                params[i] = byteList.get(i);
            }

            // 发送
            ((BottomSheetVendorModelControlsListener) requireActivity())
                    .sendVendorModelMessage(
                            mModelId,
                            mKeyIndex,
                            Integer.parseInt(opCode, 16),
                            params,
                            binding.chkAcknowledged.isChecked()
                    );
        });

        return binding.getRoot();
    }

    private boolean validateOpcode(final String opCode, final TextInputLayout opCodeLayout) {
        try {
            if (TextUtils.isEmpty(opCode)) {
                opCodeLayout.setError(getString(R.string.error_empty_value));
                return false;
            }

            if (opCode.length() % 2 != 0 || !opCode.matches(Utils.HEX_PATTERN)) {
                opCodeLayout.setError(getString(R.string.invalid_hex_value));
                return false;
            }
            if (MeshParserUtils.isValidOpcode(Integer.valueOf(opCode, 16))) {
                return true;
            }
        } catch (Exception ex) {
            opCodeLayout.setError(ex.getMessage());
            return false;
        }
        return true;
    }

    public void setReceivedMessage(final byte[] accessPayload) {
        binding.receivedMessageContainer.setVisibility(View.VISIBLE);
        binding.receivedMessage.setText(MeshParserUtils.bytesToHex(accessPayload, false));
    }
}